<script setup lang="ts">
import { computed, ref, reactive } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
import { buildUUID, cloneDeep } from '@vben/utils';
import { renderDict } from '#/utils/render';
import {
  Form,
  FormItem,
  Input,
  InputNumber,
  Select,
  Table,
  Button,
  Popconfirm,
  Space,
  message,
} from 'ant-design-vue';
import { useBeforeCloseDiff } from '#/utils/popup';
import type { Medication } from '#/api/healthPlan/config/planConfig/model';
import { medicinesListAll } from '#/api/medicine/medicines';
import type { MedicinesVO } from '#/api/medicine/medicines/model';
import type { SelectValue } from 'ant-design-vue/es/select';
import { getDictOptions } from '#/utils/dict';
import { medTempAdd, medTempUpdate, medTempInfo } from '#/api/medicine/medTemp';
import type { MedTempForm } from '#/api/medicine/medTemp/model';
import type { RuleObject } from 'ant-design-vue/es/form';

const emit = defineEmits<{ reload: [] }>();

const isUpdate = ref(false);
const title = computed(() =>
  isUpdate.value ? '编辑用药模板' : '新增用药模板',
);

// --- 表单数据 ---
const getDefaultValues = (): Partial<MedTempForm> => ({
  templateName: undefined,
  medications: [],
});

const formData = ref<MedTempForm>(getDefaultValues());
type AntdFormRules<T> = Partial<Record<keyof T, RuleObject[]>> & {
  [key: string]: RuleObject[];
};
// --- 动态表格数据 ---
const editableData: Record<string, Medication> = reactive({});
const columns = [
  { title: '药品名称', dataIndex: 'medicationName', width: '30%' },
  { title: '用药剂量', dataIndex: 'dosage', width: '30%' },
  { title: '用药频次', dataIndex: 'frequency', width: '20%' },
  { title: '操作', dataIndex: 'operation' },
];

const formRules = ref<AntdFormRules<FormData>>({
  templateName: [{ required: true, message: '请输入模板名称' }],
  medications: [
    { type: 'array', required: true, min: 1, message: '请至少添加一种药品' },
  ],
});

const { validate, validateInfos, resetFields } = Form.useForm(
  formData,
  formRules,
);

// --- 远程搜索药品 ---
const fetching = ref(false);
const drugOptions = ref<MedicinesVO[]>([]);
const searchDrugsApi = async (keyword: string) => {
  const medList = await medicinesListAll({ tradeName: keyword });
  return medList;
};

const handleDrugSearch = async (value: string) => {
  fetching.value = !!value;
  drugOptions.value = value ? await searchDrugsApi(value) : [];
};

const handleDrugChange = (
  value: SelectValue,
  option: any,
  recordKey: string | number,
) => {
  if (option) {
    editableData[recordKey]!.medicationName = option.tradeName;
    editableData[recordKey]!.medicationId = option.id;
  }
};

// --- 表格操作 ---
const getRecordKey = (record: Medication) => record.id || record.tempId!;

const edit = (record: Medication) => {
  editableData[getRecordKey(record)] = cloneDeep(record);
};

// 保存药品行编辑
const save = (record: Medication) => {
  const key = getRecordKey(record);
  const target = formData.value.medications!.find(
    (item: Medication) => getRecordKey(item) === key,
  )!;
  Object.assign(target, editableData[key]);
  delete editableData[key];
};

// 取消药品行编辑
const cancel = (record: Medication) => {
  const key = getRecordKey(record);
  delete editableData[key];
  // 如果是取消一个新建的行，则直接从数据源中移除它
  if (record.tempId) {
    formData.value.medications = formData.value.medications!.filter(
      (item: Medication) => getRecordKey(item) !== key,
    );
  }
};
const handleAddMedication = () => {
  const newMed: Medication = {
    tempId: buildUUID(),
    medicationId: '',
    medicationName: '',
    dosageValue: undefined,
    dosageUnit: undefined,
    frequency: '',
  };
  drugOptions.value = [];
  formData.value.medications!.push(newMed);
  edit(newMed);
};
const handleDeleteMedication = (record: Medication) => {
  formData.value.medications = formData.value.medications!.filter(
    (item: Medication) => getRecordKey(item) !== getRecordKey(record),
  );
};

// --- 抽屉逻辑 ---
const { onBeforeClose, markInitialized, resetInitialized } = useBeforeCloseDiff(
  {
    initializedGetter: () => JSON.stringify(formData.value),
    currentGetter: () => JSON.stringify(formData.value),
  },
);

const [BasicDrawer, drawerApi] = useVbenDrawer({
  class: 'w-[1000px]',
  onBeforeClose,
  onClosed: handleClosed,
  onConfirm: handleConfirm,
  onOpenChange: async (isOpen) => {
    if (!isOpen) return;
    drawerApi.drawerLoading(true);
    const { id } = drawerApi.getData() as { id?: string };
    isUpdate.value = !!id;
    if (id) {
      const record = await medTempInfo(id);
      formData.value = record;
    }
    await markInitialized();
    drawerApi.drawerLoading(false);
  },
});

async function handleConfirm() {
  if (Object.keys(editableData).length > 0) {
    message.warning('您有正在编辑的药品尚未保存');
    return;
  }
  try {
    drawerApi.lock(true);
    await validate();
    const data = cloneDeep(formData.value);
    data.medications?.forEach((med: Medication) => {
      if (med.tempId) med.id = med.tempId;
    });
    await (isUpdate.value ? medTempUpdate(data) : medTempAdd(data));
    resetInitialized();
    emit('reload');
    drawerApi.close();
  } catch (error) {
    console.error(error);
  } finally {
    drawerApi.lock(false);
  }
}

function handleClosed() {
  resetFields();
  formData.value = getDefaultValues();
  Object.keys(editableData).forEach((key) => delete editableData[key]);
  resetInitialized();
}
</script>

<template>
  <BasicDrawer :title="title">
    <Form :model="formData" :label-col="{ span: 3 }">
      <FormItem label="模板名称" v-bind="validateInfos.templateName">
        <Input
          v-model:value="formData.templateName"
          placeholder="请输入模板名称"
        />
      </FormItem>
      <FormItem label="用药内容" v-bind="validateInfos.medications">
        <Table
          :columns="columns"
          :data-source="formData.medications"
          :pagination="false"
          bordered
          :row-key="getRecordKey"
        >
          <template #bodyCell="{ column, text, record }">
            <template v-if="column.dataIndex === 'medicationName'">
              <div v-if="editableData[getRecordKey(record)]">
                <Select
                  v-model:value="
                    editableData[getRecordKey(record)]!.medicationName
                  "
                  show-search
                  placeholder="请输入并搜索药品"
                  :options="drugOptions"
                  :filter-option="false"
                  :not-found-content="fetching ? null : undefined"
                  :fieldNames="{ label: 'tradeName', value: 'id' }"
                  @search="handleDrugSearch"
                  @change="
                    (value, option) =>
                      handleDrugChange(value, option, getRecordKey(record))
                  "
                />
              </div>
              <template v-else>{{ text }}</template>
            </template>
            <template v-else-if="column.dataIndex === 'dosage'">
              <div v-if="editableData[getRecordKey(record)]">
                <Space.Compact>
                  <InputNumber
                    v-model:value="
                      editableData[getRecordKey(record)]!.dosageValue
                    "
                    :min="0"
                    placeholder="请输入剂量"
                    class="w-[140px]"
                  />
                  <Select
                    v-model:value="
                      editableData[getRecordKey(record)]!.dosageUnit
                    "
                    :options="getDictOptions('med_dosage_unit')"
                    placeholder="单位"
                    class="w-[80px]"
                  />
                </Space.Compact>
              </div>
              <template v-else>
                <div class="flex items-center">
                  {{ record.dosageValue }}
                  <component
                    :is="renderDict(record.dosageUnit, 'med_dosage_unit')"
                  />
                </div>
              </template>
            </template>
            <template v-else-if="column.dataIndex === 'frequency'">
              <div v-if="editableData[getRecordKey(record)]">
                <Select
                  v-model:value="editableData[getRecordKey(record)]!.frequency"
                  :options="getDictOptions('med_frequency_type')"
                  placeholder="请选择频次"
                />
              </div>
              <template v-else>
                <component
                  :is="renderDict(record.frequency, 'med_frequency_type')"
                />
              </template>
            </template>
            <template v-else-if="column.dataIndex === 'operation'">
              <div class="editable-row-operations">
                <span v-if="editableData[getRecordKey(record)]">
                  <Button
                    type="link"
                    @click="save(record)"
                    style="padding-left: 0"
                    >保存</Button
                  >
                  <Popconfirm title="确定取消吗?" @confirm="cancel(record)">
                    <Button type="link">取消</Button>
                  </Popconfirm>
                </span>
                <span v-else>
                  <Button
                    type="link"
                    @click="edit(record)"
                    style="padding-left: 0"
                    >编辑</Button
                  >
                  <Popconfirm
                    title="确定删除吗?"
                    @confirm="handleDeleteMedication(record)"
                  >
                    <Button type="link" danger>删除</Button>
                  </Popconfirm>
                </span>
              </div>
            </template>
          </template>
          <template #footer>
            <Button @click="handleAddMedication" type="dashed" block
              >+ 添加药品</Button
            >
          </template>
        </Table>
      </FormItem>
    </Form>
  </BasicDrawer>
</template>
